#ifndef _EPOLL_SVR_H_
#define _EPOLL_SVR_H_
#include <iostream>
#include <functional>
#include <string>
#include "log.hpp"
#include "Sock.hpp"
#include "epoll.hpp"
using std::cout;
using std::endl;
namespace ns_epoll
{
    //只处理读取
    class epollServer
    {
    public:
        const static uint16_t default_port = 8080;
        const static int gnum = 64;
    public:
        using func_t = std::function<void(std::string)>;
        epollServer(func_t HandlerRequest, const int &port = default_port)
            :_HandlerRequest(HandlerRequest)
            ,_port(port)
            ,_revs_num(gnum)
        {
            //1.申请对应的空间
            _revs = new struct epoll_event[_revs_num];
            //2.创建_listensock
            _listensock = Sock::Socket();
            Sock::Bind(_listensock,_port);
            Sock::Listen(_listensock);
            //3.创建epoll模型
            _epfd = Epoll::CreateEpoll();
            logMessage(DEBUG, "init success, listensock: %d, epfd: %d", _listensock, _epfd); // 3, 4
            //4.将listensock，先添加到epoll中，让epoll帮我们管理起来
            if(!Epoll::Ctl_Epoll(_epfd,EPOLL_CTL_ADD,_listensock,EPOLLIN))
            exit(4);
            logMessage(DEBUG, "add listensock to epoll success."); // 3, 4
        }

        void Accepter()
        {
            uint16_t clientport;
            std::string clientIP;
            int sock = Sock::Accept(_listensock,&clientIP,&clientport);
            if(sock < 0)
            {
                logMessage(WARNING,"accept error!");
                exit(6);
            }

            if(!Epoll::Ctl_Epoll(_epfd,EPOLL_CTL_ADD,sock,EPOLLIN))
                exit(5);
        }

        void Recver(int sock)
        {
            char buffer[1024];
            int s = recv(sock,buffer,sizeof(buffer)-1,0);
            if(s > 0)
            {
                buffer[s] = 0;
                _HandlerRequest(buffer);//处理数据
            }
            else if (s == 0)
            {
                //解除对sock的关心
                bool res = Epoll::Ctl_Epoll(_epfd,EPOLL_CTL_DEL,sock,0);
                assert(res);
                (void)res;
                //关闭sock
                close(sock);
                logMessage(NORMAL,"client %d quit, me too",sock);
            }
            else
            {
                //解除sock的关心
                bool res = Epoll::Ctl_Epoll(_epfd,EPOLL_CTL_DEL,sock,0);
                assert(res);
                (void)res;
                //关闭sock
                close(sock);
                logMessage(WARNING,"client recv %d error,close error sock",sock);
            }

        }

        void HandlerEvents(int n)
        {
            assert(n > 0);
            for(int i = 0; i < n; i++)
            {
                uint32_t revents = _revs[i].events;
                int sock = _revs[i].data.fd;
                //读事件就绪
                if(revents & EPOLLIN)
                {
                    if(sock == _listensock) Accepter();
                    else Recver(sock);
                }
            }
        }

        void LoopOnce(int timeout)
        {
            int n = Epoll::Wait_Epoll(_epfd,_revs,_revs_num,timeout);
            if(n == 0)
            {
                logMessage(DEBUG, "timeout..."); // 3, 4
            }
            else if(n == -1)
            {
                 logMessage(WARNING, "epoll wait error: %s", strerror(errno));
            }
            else
            {
                logMessage(DEBUG, "get a event");
                HandlerEvents(n);
            }
        }

        void Start()
        {
            int timeout = -1;
            while(1)
            {
                LoopOnce(timeout);
            }
        }

        ~epollServer()
        {
            if(_listensock >= 0) close(_listensock);
            if(_epfd >= 0) close(_epfd);
            if(_revs) delete []_revs;
        }
    private:
        int _listensock;
        int _epfd;//创建epoll模型的fd
        uint16_t _port;
        struct epoll_event* _revs;
        int _revs_num;//接收事件的数目
        func_t _HandlerRequest;
    };
}
#endif